package com.ruoyi.data.modbus;

import com.serotonin.modbus4j.BatchRead;
import com.serotonin.modbus4j.BatchResults;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.code.DataType;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.locator.BaseLocator;

/**
 * modbus工具类
 */
public class Modbus4jUtils {
    /**
     * 工厂。
     */
    static ModbusFactory modbusFactory;
    static {
        if (modbusFactory == null) {
            modbusFactory = new ModbusFactory();
        }
    }
    /**
     * 获取指定ip设备的master
     * @param ip
     * @return
     * @throws ModbusInitException
     */
    public static ModbusMaster getMaster(String ip){
        IpParameters params = new IpParameters();
        params.setHost(ip);
        params.setPort(600);
        ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议
        return master;
    }
//    /**
//     * 获取master
//     *
//     * @return
//     * @throws ModbusInitException
//     */
//    public static ModbusMaster getMaster() throws ModbusInitException {
//        IpParameters params = new IpParameters();
//        params.setHost("192.168.11.8");
//        params.setPort(502);
//        //
//        // modbusFactory.createRtuMaster(wapper); //RTU 协议
//        // modbusFactory.createUdpMaster(params);//UDP 协议
//        // modbusFactory.createAsciiMaster(wrapper);//ASCII 协议
//        ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议
//        master.init();
//
//        return master;
//    }

    /**
     * 读取[01 Coil Status 0x]类型 开关数据
     *
     * @param slaveId
     *            slaveId
     * @param offset
     *            位置
     * @return 读取值
     * @throws ModbusTransportException
     *             异常
     * @throws ErrorResponseException
     *             异常
     * @throws ModbusInitException
     *             异常
     */
    public static Boolean readCoilStatus(ModbusMaster  master, int slaveId, int offset)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        // 01 Coil Status
        BaseLocator<Boolean> loc = BaseLocator.coilStatus(slaveId, offset);
        Boolean value = master.getValue(loc);
        return value;
    }

    /**
     * 读取[02 Input Status 1x]类型 开关数据
     *
     * @param slaveId
     * @param offset
     * @return
     * @throws ModbusTransportException
     * @throws ErrorResponseException
     * @throws ModbusInitException
     */
    public static Boolean readInputStatus(ModbusMaster  master, int slaveId, int offset)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        // 02 Input Status
        BaseLocator<Boolean> loc = BaseLocator.inputStatus(slaveId, offset);
        Boolean value = master.getValue(loc);
        return value;
    }

    /**
     * 读取[03 Holding Register类型 2x]模拟量数据
     *
     * @param slaveId
     *            slave Id
     * @param offset
     *            位置
     * @param dataType
     *            数据类型,来自com.serotonin.modbus4j.code.DataType
     * @return
     * @throws ModbusTransportException
     *             异常
     * @throws ErrorResponseException
     *             异常
     * @throws ModbusInitException
     *             异常
     */
    public static Number readHoldingRegister(ModbusMaster  master, int slaveId, int offset, int dataType)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        // 03 Holding Register类型数据读取
        BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType);
//        System.out.println("-----------" + loc);
        Number value = master.getValue(loc);
//        System.out.println("--------------" + value);
        return value;
    }

    /**
     * 读取[04 Input Registers 3x]类型 模拟量数据
     *
     * @param slaveId
     *            slaveId
     * @param offset
     *            位置
     * @param dataType
     *            数据类型,来自com.serotonin.modbus4j.code.DataType
     * @return 返回结果
     * @throws ModbusTransportException
     *             异常
     * @throws ErrorResponseException
     *             异常
     * @throws ModbusInitException
     *             异常
     */
    public static Number readInputRegisters(ModbusMaster  master, int slaveId, int offset, int dataType)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        // 04 Input Registers类型数据读取
        BaseLocator<Number> loc = BaseLocator.inputRegister(slaveId, offset, dataType);
        Number value = master.getValue(loc);
        return value;
    }

    /**
     * 批量读取使用方法
     *
     * @throws ModbusTransportException
     * @throws ErrorResponseException
     * @throws ModbusInitException
     */
    public static void batchRead(ModbusMaster  master) throws ModbusTransportException, ErrorResponseException, ModbusInitException {

        BatchRead<Integer> batch = new BatchRead<Integer>();

        batch.addLocator(0, BaseLocator.holdingRegister(1, 1, DataType.FOUR_BYTE_FLOAT));
        batch.addLocator(1, BaseLocator.inputStatus(1, 0));

//        ModbusMaster master = Modbus4jRunner.getMaster();

        batch.setContiguousRequests(false);
        BatchResults<Integer> results = master.send(batch);
        System.out.println(results.getValue(0));
        System.out.println(results.getValue(1));
    }

    /**
     * 测试
     *
     * @param args
     */
    public static void main(String[] args) {
        try {
//            // 01测试
////            Boolean v011 = readCoilStatus(1, 0);
////            Boolean v012 = readCoilStatus(1, 3);
////            Boolean v013 = readCoilStatus(1, 6);
////            System.out.println("v011:" + v011);
////            System.out.println("v012:" + v012);
////            System.out.println("v013:" + v013);
////            // 02测试
////            Boolean v021 = readInputStatus(1, 1);
////            Boolean v022 = readInputStatus(1, 2);
////            Boolean v023 = readInputStatus(1, 5);
////            System.out.println("v021:" + v021);
////            System.out.println("v022:" + v022);
////            System.out.println("v023:" + v023);
////
////            // 03测试
//            ModbusMaster master = getMaster("192.168.1.25");
//            master.init();
//            Number v031 = readHoldingRegister(master, 1, 0, DataType.TWO_BYTE_INT_UNSIGNED);
////            Number v032 = readHoldingRegister(1, 2, DataType.FOUR_BYTE_FLOAT);// 同上
//            Number v032 = readHoldingRegister(master, 1, 40003, DataType.TWO_BYTE_INT_UNSIGNED);
//            Number v033 = readHoldingRegister(1, 0xEB03, DataType.EIGHT_BYTE_INT_UNSIGNED);
//            Number v034 = readHoldingRegister(1, 0xEB04, DataType.EIGHT_BYTE_INT_SIGNED);
//            Number v035 = readHoldingRegister(1, 0xEB03, DataType.EIGHT_BYTE_INT_UNSIGNED_SWAPPED);
//            Number v036 = readHoldingRegister(1, 0xEB04, DataType.EIGHT_BYTE_INT_SIGNED_SWAPPED);
//            System.out.println("v031:" + v031);
//            System.out.println("v032:" + v032);
//            System.out.println("v033:" + v033);
//            System.out.println("v034:" + v034);
//            System.out.println("v035:" + v035);
//            System.out.println("v036:" + v036);
////
////            // 04测试
//            Number v041 = readHoldingRegister(getMaster(),1, 0, DataType.FOUR_BYTE_FLOAT);
////            Number v042 = readInputRegisters(1, 6, DataType.FOUR_BYTE_FLOAT);//
//            System.out.println("v041:" + v041);
////            System.out.println("v042:" + v042);
//            // 批量读取
//            batchRead(master);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
